/*
 * Copyright 2008-2009 Daniel Cachapa <cachapa@gmail.com>
 * 
 * This program is distributed under the terms of the GNU General Public Licence Version 3
 * The licence can be read in its entirety in the LICENSE.txt file accompaning this source code,
 * or at: http://www.gnu.org/copyleft/gpl.html
 * 
 * This file is part of WeightWatch.
 *
 * WeightWatch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * WeightWatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the WeightWatch source code. If not, see
 * <http://www.gnu.org/licenses/>.
 */

package net.cachapa.weightwatch.ui.components;

import com.sun.lwuit.Display;
import com.sun.lwuit.TextField;
import javax.microedition.lcdui.Canvas;

public class NumericField extends TextField {
	private double upDownValueChange = 1;

	public NumericField() {
		this.setInputMode("123");
		this.setInputModeOrder(new String[]{"123"});
		this.setReplaceMenu(false);
	}
	
	public NumericField(int columns) {
		this.setInputMode("123");
		this.setInputModeOrder(new String[]{"123"});
		this.setReplaceMenu(false);
		this.setColumns(columns);
	}

	public void setUpDownValueChange(double upDownValueChange) {
		this.upDownValueChange = upDownValueChange;
	}
	
	public double getValue() {
		double value = 0;
		try {
			value = Double.parseDouble(this.getText());
		} catch (NumberFormatException numberFormatException) {
			// ignore
		}
		return value;
	}

	public void keyPressed(int keyCode) {
		String text;
		int cursorPos;
		int k = Display.getInstance().getGameAction(keyCode);
		switch (k) {
			case Display.GAME_UP:
				if (this.handlesInput()) {
					addValue(upDownValueChange);
				} else {
					super.keyPressed(keyCode);
				}
				break;

			case Display.GAME_DOWN:
				if (this.handlesInput()) {
					addValue(-upDownValueChange);
				} else {
					super.keyPressed(keyCode);
				}
				break;
				
			default:
				switch (keyCode) {
					case Canvas.KEY_STAR:
						text = this.getText();
						cursorPos = this.getCursorPosition();
						if (text.length() == 0) {
							break;
						}
						// Skip if there's a decimal separator already
						if (!hasDot(text)) {
							text = text.substring(0, cursorPos) + '.' +
								text.substring(cursorPos, text.length());
							this.setText(text);
							this.setCursorPosition(cursorPos + 1);
						}
						break;

					case Canvas.KEY_POUND:
						text = this.getText();
						cursorPos = this.getCursorPosition();
						if (text.length() == 0) {
							break;
						}
						if (text.charAt(0) != '-') {
							this.setText("-" + text);
							this.setCursorPosition(cursorPos + 1);
						} else {
							this.setText(text.substring(1));
							this.setCursorPosition(cursorPos - 1);
						}
						break;
						
					default:
						super.keyPressed(keyCode);
				}
		}
	}
	
	public void keyReleased(int keyCode) {
		switch (keyCode) {
			case Canvas.KEY_STAR:
			case Canvas.KEY_POUND:
				break;
				
			default:
				super.keyReleased(keyCode);
		}
	}

	public void setValue(double weight) {
		if (Math.abs(upDownValueChange) < 1) {
			this.setText(String.valueOf(round(weight)));
		}
		else {
			this.setText(String.valueOf((int)weight));
		}
	}

	private boolean hasDot(String text) {
		int length = text.length();
		for (int i = 0; i < length; i++) {
			if ('.' == text.charAt(i)) {
				return true;
			}
		}
		return false;
	}
	
	private void addValue(double value) {
		double textValue = (double)getValue();
		textValue += value;
		setValue(textValue);
	}
	
	private double round(double number) {
		int multiplier = Math.abs((int)(1/upDownValueChange));
		number = number * multiplier;		
		
		int dif = 1;
		if (number < 0)
			dif = -1;
		int intVal = (int)number;
		double rest = (int)((number-intVal) * 10);
		if (Math.abs(rest) < 5)
			number = intVal;
		else
			number = intVal + dif;
		
		return number / multiplier;
	}
}
